package fr.esiag.projet17.service;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

import com.sun.corba.se.impl.oa.poa.ActiveObjectMap.Key;

import fr.esiag.projet17.persistence.entity.Utilisateur;
import fr.esiag.projet17.services.transfert.KeyElement;
import fr.esiag.projet17.services.transfert.ObjectFactory;
import fr.esiag.projet17.services.transfert.UtilisateurElement;

public abstract class Wrapper<Persistent,Exchange> {

	protected Marshaller marshaller;
	private ObjectFactory objectFactory;
	protected Unmarshaller unmarshaller;
	
	public Wrapper() {
		JAXBContext jaxbContext;
		try {
			jaxbContext = JAXBContext.newInstance("fr.esiag.projet17.services.transfert");
			this.marshaller = jaxbContext.createMarshaller();
			this.unmarshaller = jaxbContext.createUnmarshaller();
			this.objectFactory = new ObjectFactory();
		} catch (JAXBException e) {
			e.printStackTrace();
		}	
	}
	
	
	protected ObjectFactory getObjectFactory(){
		return objectFactory;
	}
	
	protected byte[] marshall(Object jaxbElement) throws XMLStreamException, JAXBException{
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		XMLOutputFactory xmlFactory = XMLOutputFactory.newInstance();
		XMLStreamWriter xmlW = xmlFactory.createXMLStreamWriter(output);			
		
		marshaller.marshal(jaxbElement, xmlW);
		xmlW.flush();
		xmlW.close();
		return output.toByteArray();
	}
	
	protected JAXBElement<Exchange> unmarshall(byte[] representation) throws JAXBException{
		ByteArrayInputStream input = new ByteArrayInputStream(representation);
		JAXBElement<Exchange> element = (JAXBElement<Exchange>) unmarshaller.unmarshal(input);
		return element;
	}
	
	public Long getKeyElement(byte[] representation) throws JAXBException {
		ByteArrayInputStream input = new ByteArrayInputStream(representation);
		KeyElement element = (KeyElement)unmarshaller.unmarshal(input);
		Long id = element.getId();
		return id;
	}
	
	public byte[] getKeyRepresentation(Long id) throws JAXBException, XMLStreamException {
		KeyElement key = objectFactory.createKeyElement();
		key.setId(id);
		return marshall(key);
	}
	
	public abstract byte[] toBytes(Persistent object)throws JAXBException,XMLStreamException;
	public abstract Persistent toElement(byte[] representation) throws JAXBException,XMLStreamException;
}
